--part of winuser that deals only with messages.
setfenv(1, require'winapi')
require'winapi.winuser'
require'winapi.windows'

ffi.cdef[[
typedef struct tagMSG {
	 HWND        hwnd;
	 UINT        message;
	 union {
		WPARAM      wParam;
		int         signed_wParam;
	 };
	 LPARAM      lParam;
	 DWORD       time;
	 POINT       pt;
} MSG, *PMSG, *NPMSG, *LPMSG;

BOOL GetMessageW(
	  LPMSG lpMsg,
	  HWND hWnd,
	  UINT wMsgFilterMin,
	  UINT wMsgFilterMax);

BOOL TranslateMessage(const MSG *lpMsg);

int TranslateAcceleratorW(
     HWND hWnd,
     HACCEL hAccTable,
     LPMSG lpMsg);

LRESULT DispatchMessageW(const MSG *lpMsg);

BOOL IsDialogMessageW(
     HWND hDlg,
     LPMSG lpMsg);

void PostQuitMessage(int nExitCode);

LRESULT SendMessageW(
	  HWND hWnd,
	  UINT Msg,
	  WPARAM wParam,
	  LPARAM lParam);
]]

function GetMessage(msg, window, WMmin, WMmax)
	--print('>', '%s 0x%.4x %s (%s, %s)' % {tostring(msg.hwnd), tonumber(msg.message), findname('WM_', tonumber(msg.message)), tostring(msg.wParam), tostring(msg.lParam)})
	return checkpoz(ffi.C.GetMessageW(msg, window, flags(WMmin), flags(WMmax)))
end

TranslateMessage = ffi.C.TranslateMessage
DispatchMessage = ffi.C.DispatchMessageW

function IsDialogMessage(hwnd, msg)
	return ffi.C.IsDialogMessageW(hwnd, msg) ~= 0
end

function PostQuitMessage(exitcode)
	ffi.C.PostQuitMessage(exitcode or 0)
end

function SendMessage(subject, WM, wparam, lparam)
	if type(wparam) == 'nil' then wparam = 0 end
	if type(lparam) == 'nil' then lparam = 0 end
	return ffi.C.SendMessageW(subject, WM,
										ffi.cast('WPARAM', wparam),
										ffi.cast('LPARAM', lparam))
end

SNDMSG = SendMessage --less typing on those tedious macros

function MessageLoop(msg) --you can do os.exit(MessageLoop())
	msg = types.MSG(msg)
	while GetMessage(msg) ~= 0 do
		local hwnd = GetActiveWindow()
		if hwnd == nil or not IsDialogMessage(hwnd, msg) then --make tab work
			TranslateMessage(msg) --make keyboard work
			DispatchMessage(msg) --make everything else work
		end
	end
	return msg.signed_wParam --WM_QUIT returns 0 and an int exit code in wParam
end

